package com.android.kotlincoroutinemvvmdemo
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.buffer
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.debounce
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flatMapConcat
import kotlinx.coroutines.flow.flatMapMerge
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.runningFold
import kotlinx.coroutines.flow.runningReduce
import kotlinx.coroutines.flow.sample
import kotlinx.coroutines.flow.zip
import kotlinx.coroutines.runBlocking
import org.junit.Test

class FlowDemo {
    @Test
    fun testReduce() = runBlocking {
        //reduce执行累加操作
        val result = listOf(1, 2, 3).reduce { a, b ->
            a + b
        }
        println("result:${result}")
    }

    @Test
    fun testRunningFold() = runBlocking {
        //runningFold分步累加结合
        flowOf(1, 2, 3).runningFold("a") { a, b ->
            a + b
        }.collect {
            println("result:${it}")
        }
    }

    @Test
    fun testRunningReduce() = runBlocking {
        //runningReduce分步累加
        flowOf(1,2,3).runningReduce { a, b ->
            a + b
        }.collect {
           doPrint(it)
        }
    }

    @Test
    fun testDebounce() = runBlocking {
        //debounce用于限流  符合条件的才接收
        flow {
            emit(1)
            delay(590)
            emit(2)
            delay(590)
            emit(3)
            delay(1010)
            emit(4)
            delay(1010)
        }.debounce(
            1000
        ).collect {
            doPrint(it)
        }
    }

    @Test
    fun testSample() = runBlocking {
        //sample每一个周期接收一个元素
        flow {
            repeat(5) {
                emit(it)
                delay(80)
            }
        }.sample(100)
         .collect {
             doPrint(it)
         }
        //sample(periodMillis)传入的是周期时间
    }

    @Test
    fun testFlatMapMerge() = runBlocking {
        //多个flowOf执行操作
        flowOf(1, 3).flatMapMerge {
            flowOf("$it a", "$it b")
        }.collect {
            doPrint(it)
        }
    }

    @Test
    fun testFlatMapConcat() = runBlocking {
        flowOf(1, 2).flatMapConcat {
            flowOf("${it} a", "${it} b")
        }.collect {
            doPrint(it)
        }
    }

    @Test
    fun testOnEach() = runBlocking {
        //onEach  collect交叉执行
        flowOf("A", "B", "C", "D").onEach {
            println("1 ${it}")
        }.collect {
            println("2 ${it}")
        }
    }

    @Test
    fun testBuffer() = runBlocking {
        //buffer缓冲作用  先执行onEach  再执行collect
        flowOf("A","B","C","D").onEach {
            println("1 ${it}")
        }.buffer().collect {
            println("2 ${it}")
        }
    }

    @Test
    fun testCombine() = runBlocking {
        flowOf(1, 3).combine(
            flowOf("A","B")
        ) { a,b ->
            "${a} ${b}"
        }.collect {
            doPrint(it)
        }
    }

    @Test
    fun testZip() = runBlocking {
        //zip符合木桶理论,两个flowOf元素结合时数量小的为各自总量元素值.
        flowOf(1, 3).zip(
            flowOf("A", "B", "C")
        ) { a, b ->
            "${a} ${b}"
        }.collect {
            doPrint(it)
        }
    }

    @Test
    fun testDistinctUntilChanged() = runBlocking {
        //防止出现相连两个元素是重复的
        flowOf(1, 2, 2, 3, 4, 5, 5, 6, 7, 2)
            .distinctUntilChanged()
            .collect {
                doPrint(it)
            }
    }

    companion object {
        fun doPrint(value: Any) {
            println("result:${value}")
        }
    }
}